package com.twang.stock.task;

import com.alibaba.fastjson.JSONObject;
import com.twang.stock.Entity.ShiShiData;
import com.twang.stock.common.DateUtil;
import com.twang.stock.common.http.HtmlTools;
import com.twang.stock.dto.StockMinutesMessage;
import com.twang.stock.entity.CompanyCodeInfo;
import com.twang.stock.entity.CompanyStock;
import com.twang.stock.entity.CompanyStockMinutes;
import com.twang.stock.mapper.CompanyCodeInfoMapper;
import com.twang.stock.mapper.CompanyStockMapper;
import com.twang.stock.mapper.CompanyStockMinutesMapper;
import com.twang.stock.redis.RedisUtil;
import com.twang.stock.rocketMq.RocketMQProducer;
import com.twang.stock.service.CompanyStockMinutesService;
import com.twang.stock.service.jinyan.CommonService;
import com.twang.stock.email.SendmailService;
import com.twang.stock.task.old.BaseTask;
import com.twang.stock.threadPool.AsycTaskExecutorConfig;
import com.twang.stock.utils.date.DateUtils;
import com.twang.stock.utils.date.HolidayCopy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @param ：
 * 每日14：57更新
 * 即时--http://data.10jqka.com.cn/funds/gnzjl/ajax/1/free/1/
 *             3日：http://data.10jqka.com.cn/funds/gnzjl/board/3/ajax/1/free/1/
 *             5日：http://data.10jqka.com.cn/funds/gnzjl/board/5/ajax/1/free/1/
 *           明细：http://q.10jqka.com.cn/gn/detail/code/300845/
 */
@Slf4j
@Service
public class StockMinutesTask extends BaseTask {


    @Autowired
    private AsycTaskExecutorConfig asycTaskExecutorConfig;

    @Resource
    private CompanyCodeInfoMapper companyCodeInfoMapper;

    @Resource
    private CompanyStockMinutesMapper companyStockMinutesMapper;

    @Autowired
    private CompanyStockMinutesService companyStockMinutesService;

    @Autowired
    private RedisUtil redisUtil;

    private static String COMPANY_STOCK_CODE_LIST = "COMPANY_STOCK_CODE_LIST_";

    @Resource
    private CompanyStockMapper companyStockMapper;

    @Resource
    private CommonService commonService;

    @Autowired
    private SendmailService sendmailService;

    @Autowired
    private RocketMQProducer rocketMQProducer;


//    @Scheduled(cron = "0 0/1 * * * ?")
    public void excute() throws InterruptedException {
        if (!isWorkTradeTime()) {
            return;
        }

        //
        initMinutesData();
        //
        涨停板连扳数据();

    }

    public void 涨停板连扳数据() {
        StockMinutesMessage message = new StockMinutesMessage();
        message.setMinutes(HolidayCopy.getHHmmss().substring(8, 12));
        message.setDate(HolidayCopy.getRealToday());
        message.setType(StockMinutesMessage.TYPE_ZHANG_TING_BAN_LIAN_BAN);
        log.info(">>>>>>>>>>>> 涨停板连扳数据  message={}", JSONObject.toJSONString(message));
        rocketMQProducer.sendOneWay(JSONObject.toJSONString(message));
    }

    public void initMinutesData() {
        try {
            List<CompanyCodeInfo> list;
            Object object = redisUtil.get(COMPANY_STOCK_CODE_LIST + HolidayCopy.getRealToday());
            if (null != object) {
                list = (List<CompanyCodeInfo>) object;
            } else {
                list = companyCodeInfoMapper.selectAll();
                redisUtil.set(COMPANY_STOCK_CODE_LIST + HolidayCopy.getRealToday(), list);
            }
            List<CompanyCodeInfo> list1 = list.stream().filter(item -> !(item.getShortName().contains("退") || item.getShortName().contains("B") || item.getShortName().contains("*ST") || item.getShortName().contains("ST") || item.getShortName().contains("*"))).collect(Collectors.toList());
            list1 = companyCodeInfoMapper.getZiXuan();
            {
                for (CompanyCodeInfo companyCodeInfo : list1) {
                    asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
                        try {
                            covertDTO(companyCodeInfo.getCompanyCode());
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    });
                }
            }
//            StringBuffer code = new StringBuffer("");
//            int i = 0;
//            for (CompanyCodeInfo companyCodeInfo : list1) {
//                if (i < 100) {
//                    code.append(companyCodeInfo.getCompanyCode()).append(",");
//                } else {
//                    i=0;
//                    String finalCode = code.toString();
//                    asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
//                        try {
//                            covertDTO(finalCode);
//                        } catch (InterruptedException e) {
//                            throw new RuntimeException(e);
//                        }
//                    });
//                    code = new StringBuffer("");
//                    code.append(companyCodeInfo.getCompanyCode()).append(",");
//                }
//                i++;
//            }
//            covertDTO(code.toString());
        } catch (Exception e) {
            throw e;
        } finally {
            asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
                if (!isWorkTradeTime()) {
                    log.info("行成交额初始化开始--->非工作日不执行");
                    return;
                } else {
                    extractedChengJiaoe();
                }
            });
        }
    }

    public void extractedChengJiaoe() {
        StockMinutesMessage message = new StockMinutesMessage();
        message.setMinutes(HolidayCopy.getHHmmss().substring(8, 12));
        message.setDate(HolidayCopy.getRealToday());
        message.setType(StockMinutesMessage.TYPE_MINUTES_CHENG_JIAO_E);
        log.info(">>>>>>>>>>>> 行成交额初始化开始  message={}", JSONObject.toJSONString(message));
        rocketMQProducer.sendOneWay(JSONObject.toJSONString(message));
    }

    /**
     * @param code
     * @throws InterruptedException
     */
    private void covertDTO(String code) throws InterruptedException {
        StockMinutesMessage message = new StockMinutesMessage();
        message.setMinutes(HolidayCopy.getHHmmss().substring(8, 12));
        message.setDate(HolidayCopy.getRealToday());
        message.setType(StockMinutesMessage.TYPE_MINUTES);
        message.setCode(code);
        log.info(">>>>>>>>>>>> covertDTO  message={}", JSONObject.toJSONString(message));
        rocketMQProducer.sendOneWay(JSONObject.toJSONString(message));
    }

    /**
     * 读取数据
     *
     * @param code
     * @return
     */
    public CompanyStockMinutes getZDT(String code) {
        CompanyStockMinutes companyStockMinutes = new CompanyStockMinutes();
        companyStockMinutes.setDate(DateUtil.getToday().substring(0, 8));
        companyStockMinutes.setMinutes(HolidayCopy.getHHmmss().substring(8, 12));
        try {
            List<ShiShiData> shiShiDataList = HtmlTools.getGpdatas(Lists.newArrayList(code));
            if (CollectionUtils.isEmpty(shiShiDataList)) {
                //log.info("code={} is null",code);
                return null;
            }
            ShiShiData shiShiData = shiShiDataList.get(0);
            /**
             * 单独启线程池优化速度
             */
            asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
                insertData(companyStockMinutes, shiShiData);
            });
        } catch (Exception e) {
            log.error("erro={}", e);
        }
        return companyStockMinutes;
    }

    /**
     * @param companyStockMinutes
     * @param shiShiData
     */
    private void insertData(CompanyStockMinutes companyStockMinutes, ShiShiData shiShiData) {
        companyStockMinutes.setCompanyCode(shiShiData.getCode());
        companyStockMinutes.setCompanyName(shiShiData.getGpname());
        companyStockMinutes.setMinutes(null == redisUtil.get(StockLastMinutesETask.key) ? shiShiData.getGptime() : "1500");
        companyStockMinutes.setDate(shiShiData.getGpdate());

        //排除该时段的计算
        List<String> minutes = Lists.newArrayList("0929");
        if (StringUtils.isNotBlank(companyStockMinutes.getMinutes()) && minutes.contains(companyStockMinutes.getMinutes())) {
            log.info("该时间段不计算数据 {}", companyStockMinutes.getMinutes());
            return;
        }
        if (DateUtils.JudgeTime("09:26:00", "09:29:00")) {
            if (StringUtils.isNotBlank(companyStockMinutes.getMinutes())) {
                log.info("该时间9:00-09:30段不计算数据 {}", companyStockMinutes.getMinutes());
                return;
            }
        }
        companyStockMinutes.setPrice(new BigDecimal(shiShiData.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP));
        companyStockMinutes.setTradeSum(new BigDecimal(shiShiData.getAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
        companyStockMinutes.setTradeVol(new BigDecimal(shiShiData.getSumvol()).setScale(2, BigDecimal.ROUND_HALF_UP));
        companyStockMinutes.setZhangDie(shiShiData.getZhangdie());
        try {
            CompanyStockMinutes temp = new CompanyStockMinutes();
            temp.setDate(companyStockMinutes.getDate());
            temp.setMinutes(companyStockMinutes.getMinutes());
            temp.setCompanyCode(companyStockMinutes.getCompanyCode());
            if (CollectionUtils.isNotEmpty(companyStockMinutesMapper.select(temp))) {
                companyStockMinutesMapper.delete(temp);
            }
            try {
                //更新分钟量能
                Example example = new Example(CompanyStockMinutes.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("date", companyStockMinutes.getDate());
                criteria.andEqualTo("companyCode", companyStockMinutes.getCompanyCode());
                example.orderBy("id").desc();
                List<CompanyStockMinutes> list = companyStockMinutesMapper.selectByExample(example);
                if (CollectionUtils.isNotEmpty(list)) {
                    CompanyStockMinutes last = list.get(0);

                    if (null == last) {
                        companyStockMinutes.setVol(BigDecimal.ZERO);
                        companyStockMinutes.setAmount(BigDecimal.ZERO);
                        companyStockMinutes.setCreateTime(new Date());
                    } else {
                        companyStockMinutes.setVol(companyStockMinutes.getTradeVol().subtract(last.getTradeVol()).setScale(2, BigDecimal.ROUND_HALF_UP));
                        companyStockMinutes.setAmount(companyStockMinutes.getTradeSum().subtract(last.getTradeSum()));
                        companyStockMinutes.setCreateTime(new Date());
                    }
                    //判断分时量能的大小，做预警
                    try {
                        warn(companyStockMinutes);
                    } catch (Exception e) {
                        log.error("预警发生异常", e);
                    }
                }
            } catch (Exception e) {
                log.error("更新分钟量能  异常 {}", e);
            }
            Example example = new Example(CompanyStockMinutes.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("date", companyStockMinutes.getDate());
            criteria.andEqualTo("companyCode", companyStockMinutes.getCompanyCode());
            criteria.andEqualTo("minutes", companyStockMinutes.getMinutes());
            example.orderBy("id").desc();
            List<CompanyStockMinutes> list = companyStockMinutesMapper.selectByExample(example);
            if (CollectionUtils.isNotEmpty(list)) {
                CompanyStockMinutes last = list.get(0);
                companyStockMinutes.setId(last.getId());
                companyStockMinutesMapper.updateByPrimaryKey(companyStockMinutes);
            } else {
                companyStockMinutesMapper.insert(companyStockMinutes);
            }


        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (DateUtils.JudgeTime("09:59:00", "10:01:00")) {
                String today30MinVolKey_ = "today30MinVol_" + companyStockMinutes.getCompanyCode() + "_" + HolidayCopy.getRealToday();
                redisUtil.del(today30MinVolKey_);
                log.info("缓存KEY删除成功：{}", today30MinVolKey_);
            }
        }
    }

    /**
     * 自选预警
     *
     * @param companyStockMinutes
     */
    private void warn(CompanyStockMinutes companyStockMinutes) {
        List<String> ids = Arrays.asList(commonService.getValue("warn_ID").toString().split(","));
        for (String id : ids) {
            CompanyStock paramCount = new CompanyStock();
            paramCount.setCompanyCode(companyStockMinutes.getCompanyCode());
            paramCount.setUserId(Integer.valueOf(id));
            if (companyStockMapper.selectCount(paramCount) > 0) {
                List<String> dates = companyStockMinutesMapper.queryDates();
                /** 昨天 */
                String date = dates.get(dates.size() - 2);
                BigDecimal yestoDayMaxVol = companyStockMinutesService.getMaxVol(date, companyStockMinutes.getCompanyCode());
                if (companyStockMinutes.getVol().compareTo(yestoDayMaxVol) > 0) {
                    CompanyStock info = companyStockMapper.selectOne(paramCount);
                    String str = String.format("个股异动：【涨跌幅：%s 】time=%s  vol=%s  昨日vol=%s ！ 关联逻辑：%s ", companyStockMinutes.getZhangDie(), companyStockMinutes.getMinutes(), companyStockMinutes.getVol(), yestoDayMaxVol, info.getStockDesc());
                    sendmailService.sendMailWithEmail(str, companyStockMinutes.getCompanyName(), companyStockMinutes.getCompanyName(), Long.valueOf(id));
                }
            }
        }
    }

    /**
     * 修复历史数据
     */
    public void queryDatesFixHistoryData() {
        List<String> dateList = Lists.newArrayList("20220317", "20220307", "20220308", "20220309", "20220310", "20220311", "20220314", "20220315", "20220316");
        dateList.forEach(date -> {
            List<CompanyCodeInfo> list = companyCodeInfoMapper.selectAll();
            list.forEach(item -> {
                /** 多线程 */
                asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
                    updateHistoryVolAmount(item.getCompanyCode(), date);
                });
            });
        });
    }

    public void updateHistoryVolAmount(String code, String date) {
        Example example = new Example(CompanyStockMinutes.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("date", date);
        criteria.andEqualTo("companyCode", code);
        example.orderBy("id").asc();
        List<CompanyStockMinutes> history = companyStockMinutesMapper.selectByExample(example);
        for (int i = history.size() - 1; i >= 0; i--) {
            /** 多线程 */
            int finalI = i;
            asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
                if (finalI == 0) {
                    CompanyStockMinutes newDate = history.get(finalI);
                    newDate.setVol(BigDecimal.ZERO);
                    newDate.setAmount(BigDecimal.ZERO);
                    companyStockMinutesMapper.updateByPrimaryKey(newDate);
                } else {
                    CompanyStockMinutes newDate = history.get(finalI);
                    CompanyStockMinutes oldDate = history.get(finalI - 1);
                    newDate.setVol(newDate.getTradeVol().subtract(oldDate.getTradeVol()).setScale(2, BigDecimal.ROUND_HALF_UP));
                    newDate.setAmount(newDate.getTradeSum().subtract(oldDate.getTradeSum()));
                    companyStockMinutesMapper.updateByPrimaryKey(newDate);
                }

            });
        }
    }


}
